package com.ls.server.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ls.server.domain.ChatAttachment;
import com.ls.server.mapper.ChatAttachmentMapper;
import com.ls.server.service.ChatAttachmentService;
import com.ls.server.vo.ChatAttachmentVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 聊天附件Service实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChatAttachmentServiceImpl extends ServiceImpl<ChatAttachmentMapper, ChatAttachment> implements ChatAttachmentService {

    @Value("${file.upload.path:/uploads}")
    private String uploadPath;
    
    @Value("${file.access.url:/files}")
    private String fileAccessUrl;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long uploadAttachment(MultipartFile file, String sessionId, Long userId) {
        if (file.isEmpty()) {
            throw new RuntimeException("上传文件不能为空");
        }
        
        try {
            // 生成文件存储路径
            String today = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            String relativePath = "/chat/" + today;
            String fullPath = uploadPath + relativePath;
            
            // 创建目录
            File dir = new File(fullPath);
            if (!dir.exists()) {
                if (!dir.mkdirs()) {
                    throw new RuntimeException("创建目录失败：" + fullPath);
                }
            }
            
            // 生成唯一文件名
            String originalFilename = file.getOriginalFilename();
            String fileExtension = "";
            if (originalFilename != null && originalFilename.contains(".")) {
                fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            }
            String filename = UUID.randomUUID().toString().replace("-", "") + fileExtension;
            String filePath = relativePath + "/" + filename;
            
            // 保存文件
            Path targetPath = Paths.get(uploadPath + filePath);
            Files.copy(file.getInputStream(), targetPath);
            
            // 保存附件信息到数据库
            ChatAttachment attachment = new ChatAttachment();
            attachment.setSessionId(sessionId);
            attachment.setUserId(userId);
            attachment.setFileName(originalFilename);
            attachment.setFileSize(file.getSize());
            attachment.setFileType(file.getContentType());
            attachment.setFilePath(filePath);
            attachment.setCreateTime(LocalDateTime.now());
            
            baseMapper.insert(attachment);
            
            return attachment.getId();
        } catch (IOException e) {
            log.error("文件上传失败", e);
            throw new RuntimeException("文件上传失败：" + e.getMessage());
        }
    }

    @Override
    public List<ChatAttachmentVO> listByMessageId(Long messageId) {
        LambdaQueryWrapper<ChatAttachment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatAttachment::getMessageId, messageId);
        
        List<ChatAttachment> attachments = baseMapper.selectList(wrapper);
        return convertToVoList(attachments);
    }

    @Override
    public List<ChatAttachmentVO> listBySessionId(String sessionId) {
        LambdaQueryWrapper<ChatAttachment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatAttachment::getSessionId, sessionId);
        
        List<ChatAttachment> attachments = baseMapper.selectList(wrapper);
        return convertToVoList(attachments);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean linkAttachmentsToMessage(Long messageId, List<Long> attachmentIds) {
        if (attachmentIds == null || attachmentIds.isEmpty()) {
            return false;
        }
        
        for (Long attachmentId : attachmentIds) {
            ChatAttachment attachment = baseMapper.selectById(attachmentId);
            if (attachment != null) {
                attachment.setMessageId(messageId);
                baseMapper.updateById(attachment);
            }
        }
        
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAttachment(Long attachmentId) {
        ChatAttachment attachment = baseMapper.selectById(attachmentId);
        if (attachment == null) {
            return false;
        }
        
        // 删除文件
        String filePath = uploadPath + attachment.getFilePath();
        File file = new File(filePath);
        if (file.exists() && file.isFile()) {
            if (!file.delete()) {
                log.warn("文件删除失败：{}", filePath);
            }
        }
        
        // 删除数据库记录
        return baseMapper.deleteById(attachmentId) > 0;
    }
    
    /**
     * 将实体转换为VO
     */
    private ChatAttachmentVO convertToVo(ChatAttachment attachment) {
        ChatAttachmentVO vo = new ChatAttachmentVO();
        BeanUtils.copyProperties(attachment, vo);
        
        // 设置附件ID
        vo.setAttachmentId(attachment.getId());
        
        // 设置文件URL
        vo.setFileUrl(fileAccessUrl + attachment.getFilePath());
        
        return vo;
    }
    
    /**
     * 将实体列表转换为VO列表
     */
    private List<ChatAttachmentVO> convertToVoList(List<ChatAttachment> attachments) {
        if (attachments == null || attachments.isEmpty()) {
            return new ArrayList<>();
        }
        return attachments.stream()
                .map(this::convertToVo)
                .collect(Collectors.toList());
    }
} 